#include "property.hpp"

#include "qbe/src/ecs/app.hpp"

#include "qbe/src/ecs/query.hpp"

#include "qbe/src/axis/axis.hpp"
#include "qbe/src/input/input.hpp"
#include "qbe/src/select/select.hpp"
#include "qbe/src/state/state.hpp"
#include "qbe/src/undoRedo/undoRedo.hpp"
#include "qbe/src/utils/utils.hpp"

#include "qbe/src/layout/layout.hpp"

#include "qlib/all.h"

#include "qbe/src/ui_message/message.h"

namespace qbe::propertyUi {

void update(ecs::Query query, ecs::Bus& bus) {
  auto& undoRedoModule = query.get_resource<undoRedoT::UndoRedoModule>();
  auto& cmd = query.get_resource<layout::LayoutCmd>();
  auto& cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;
  auto& sele_event_writer = query.get_event_writer<select::Event>();

  auto receive = bus.receive<qbe::UiMessage::AttributePanel>();
  auto current_lib = query.get_resource<qlib::Library::s_ptr>();

  if (!receive.empty()) {
    // 发送选择对象
    qbe::UiMessage::SelectObjProperty send_event;

    {
      auto view_select = reg.view<select::SelectTag, qlib::Polygon::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Polygon::s_ptr poly) { send_event.polygons[e] = poly; });
    }
    {
      auto view_select = reg.view<select::SelectTag, qlib::Path::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Path::s_ptr line) { send_event.lines[e] = line; });
    }
    {
      auto view_select = reg.view<select::SelectTag, qlib::Ellipse::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Ellipse::s_ptr ellipse) { send_event.ellipses[e] = ellipse; });
    }
    {
      auto view_select = reg.view<select::SelectTag, qlib::Fan::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Fan::s_ptr fan) { send_event.fans[e] = fan; });
    }
    {
      auto view_select = reg.view<select::SelectTag, qlib::Label::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Label::s_ptr label) { send_event.labels[e] = label; });
    }
    {
      auto view_select = reg.view<select::SelectTag, qlib::Rectangle::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Rectangle::s_ptr rectangle) { send_event.rectangles[e] = rectangle; });
    }

    {
      auto view_select = reg.view<select::SelectTag, qlib::Text::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Text::s_ptr text) { send_event.texts[e] = text; });
    }

    {
      auto view_select = reg.view<select::SelectTag, qlib::Ruler::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Ruler::s_ptr ruler) { send_event.rulers[e] = ruler; });
    }

    {
      auto view_select = reg.view<select::SelectTag, qlib::Reference::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Reference::s_ptr reference) { send_event.references[e] = reference; });
    }

    {
      auto view_select = reg.view<select::SelectTag, qlib::Pin::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::Pin::s_ptr pin) { send_event.pins[e] = pin; });
    }

    {
      auto view_select = reg.view<select::SelectTag, qlib::KeyPoint::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::KeyPoint::s_ptr key_point) { send_event.key_points[e] = key_point; });
    }
    {
      auto view_select = reg.view<select::SelectTag, qlib::ViewArea3D::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::ViewArea3D::s_ptr view_area) { send_event.view_area_3Ds[e] = view_area; });
    }
    {
      auto view_select = reg.view<select::SelectTag, qlib::SectionArea3D::s_ptr>();
      view_select.each([&send_event](entt::entity e, qlib::SectionArea3D::s_ptr section_area) { send_event.section_area_3Ds[e] = section_area; });
    }

    if (!send_event.empty()) {
      bus.send(send_event);
    }
  }

  // 接收更改对象
  auto rece_event = bus.receive<qbe::UiMessage::ChangeObjProperty>();

  if (!rece_event.empty()) {
    undoRedoModule.start(cell);

    for (auto [entity, polygon] : rece_event.back().polygons) {
      undoRedoModule.change(entity);

      auto& poly = reg.get<qlib::Polygon::s_ptr>(entity);
      (*poly) = *polygon;

      cmd.update(entity);
    }

    for (auto [entity, path] : rece_event.back().lines) {
      undoRedoModule.change(entity);

      auto& path_src = reg.get<qlib::Path::s_ptr>(entity);
      (*path_src) = *path;

      cmd.update(entity);
    }

    for (auto [entity, rectangle] : rece_event.back().rectangles) {
      undoRedoModule.change(entity);

      auto& rectangle_src = reg.get<qlib::Rectangle::s_ptr>(entity);
      (*rectangle_src) = *rectangle;

      cmd.update(entity);
    }

    for (auto [entity, ellipse] : rece_event.back().ellipses) {
      undoRedoModule.change(entity);

      auto& ellipse_src = reg.get<qlib::Ellipse::s_ptr>(entity);
      (*ellipse_src) = *ellipse;

      cmd.update(entity);
    }

    for (auto [entity, fan] : rece_event.back().fans) {
      undoRedoModule.change(entity);

      auto& fan_src = reg.get<qlib::Fan::s_ptr>(entity);
      (*fan_src) = *fan;

      cmd.update(entity);
    }

    for (auto [entity, label] : rece_event.back().labels) {
      undoRedoModule.change(entity);

      auto& label_src = reg.get<qlib::Label::s_ptr>(entity);
      (*label_src) = *label;

      cmd.update(entity);
    }

    for (auto [entity, ruler] : rece_event.back().rulers) {
      undoRedoModule.change(entity);

      auto& ruler_src = reg.get<qlib::Ruler::s_ptr>(entity);
      (*ruler_src) = *ruler;

      cmd.update(entity);
    }

    for (auto [entity, text] : rece_event.back().texts) {
      undoRedoModule.change(entity);

      auto& text_src = reg.get<qlib::Text::s_ptr>(entity);
      (*text_src) = *text;

      cmd.update(entity);
    }

    for (auto [entity, pin] : rece_event.back().pins) {
      undoRedoModule.change(entity);

      auto& pin_src = reg.get<qlib::Pin::s_ptr>(entity);
      (*pin_src) = *pin;

      cmd.update(entity);
    }

    for (auto [entity, key_point] : rece_event.back().key_points) {
      undoRedoModule.change(entity);

      auto& key_point_src = reg.get<qlib::KeyPoint::s_ptr>(entity);
      (*key_point_src) = *key_point;

      cmd.update(entity);
    }

    for (auto [entity, view_area] : rece_event.back().view_area_3Ds) {
      undoRedoModule.change(entity);

      auto& view_area_src = reg.get<qlib::ViewArea3D::s_ptr>(entity);
      (*view_area_src) = *view_area;

      cmd.update(entity);
    }

    for (auto [entity, section_area] : rece_event.back().section_area_3Ds) {
      undoRedoModule.change(entity);

      auto& section_area_src = reg.get<qlib::SectionArea3D::s_ptr>(entity);
      (*section_area_src) = *section_area;

      cmd.update(entity);
    }

    for (auto [entity, reference] : rece_event.back().references) {
      reg.remove<select::SelectTag>(entity);
      undoRedoModule.dele(entity);
      cmd.remove(entity);
      entt::entity e_reference = cmd.add(reference);
      cmd.add_cell(reference->cell);
      undoRedoModule.add(e_reference);
      cmd.update(e_reference);
      reg.emplace_or_replace<select::SelectTag>(e_reference);
      bus.send<qbe::UiMessage::UpdateFileLisetFromLibrary>(qbe::UiMessage::UpdateFileLisetFromLibrary{current_lib});
    }

    for (auto [entity, path_topolygon] : rece_event.back().path_topolygon) {
      // 删除原有线对象
      reg.remove<select::SelectTag>(entity);
      undoRedoModule.dele(entity);
      cmd.remove(entity);
      // 添加转换的多边形对象
      entt::entity e_polygon = cmd.add(path_topolygon);
      undoRedoModule.add(e_polygon);
      cmd.update(e_polygon);
      reg.emplace_or_replace<select::SelectTag>(e_polygon);
    }

    for (auto entity : rece_event.back().delete_objs) {
      // 删除原有线对象
      undoRedoModule.dele(entity);
      cmd.remove(entity);
      reg.remove<select::SelectTag>(entity);
    }

    for (auto entity : rece_event.back().uncheck) {
      // 取消选中对象
      reg.remove<select::SelectTag>(entity);
    }

    sele_event_writer.send({select::Code::SelectUpdate});
    sele_event_writer.send({select::Code::HoverUpdate});

    undoRedoModule.end();
  }
}

void Plugin::build(ecs::App& app) {
  app.add_stage<UpdateStage>();

  app.add_systems<UpdateStage>(update);
}

}  // namespace qbe::propertyUi